跳表


跳表原理

在单向链表上,要查询一个数据,只能从头开始遍历,时间复杂度为O(n),那么有办法提高链表的查询速度吗?有,那就是跳表。

使用跳表有个前提,就是单链表本身是有序的

跳表的原理就是在原链表的基础上,每2个节点,创建一个索引,称之为一级索引,大致如下:

假设你要找6这个元素,原链表需要从1开始遍历,一共需要6次访问才能找到6,使用了跳表的一级索引之后,只需要1->3->5->6这个路径就找到了6。

在一级索引之上,我们可以再用同样的方法创建二级索引:

使用了二级索引,又减少了一次操作

当原链表数据量非常庞大时,我们可以创建多级索引。数据量越多,索引数越多,节省的时间也就越多。

可以看出,跳表是一个用空间换时间的数据结构

时间复杂度

假设单链表的长度为n,一共有k级索引,且最高级索引只有2个节点。

那么一级索引的的长度约为 $\frac {n} {2}$,二级索引长度就是$\frac {n} {4}$$,k级索引长度就是$$\frac {n} {2^k}$

因为最高级节点数为2,由$\frac {n} {2^k}$ = 2 可以得出索引数量k为
$$
\begin{align}
\frac {n} {2^k} &= 2 \\
n &= 2^{k+1} \\
k + 1 &= \log_2 n \\
k &= \log_2 n -1
\end{align}
$$
加上单链表,整个跳表的高度为$ h = \log_2 n $

如果每一层需要访问节点数为m,那么时间复杂度即为$O(m\log_2 n) $,平均时间复杂度可以省略倍数m,因此跳表的时间复杂度为$O(\log_2 n)$

空间复杂度

假设单链表长度为n,有k级索引,且最高级索引只有2个节点

一级索引的的长度约为 $\frac {n} {2}$,二级索引长度就是$\frac {n} {4}$$,k级索引长度就是$$\frac {n} {2^k}$

整个跳表的节点数为
$$
n + \frac {n} {2} + \frac {n} {4} + … + 2 = n(1 + \frac {1} {2} + \frac {1} {4} + … + 2)
$$
省略倍数,因此跳表空间复杂度为$O(n)$

如果觉得消耗内存太多,可以每3个节点生成一个索引,甚至每x个节点生成一个索引。

不过实际上不用太担心空间消耗问题,在实际开发中,原链表中的数据一般都是一个对象,而索引实际上只保存了对象的引用而已,不会占太多内存。

不仅如此,我们还可以将上图的跳表结构略作改造,不额外使用列表去保存索引,而是直接在原链表上做索引,又节省了不少空间:

文章作者: 周君
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 周君 !
评论